﻿using System;
using System.Linq;
using System.Web.Mvc;
using Inscriptionem.Authorization;
using Inscriptionem.Controllers.Base;
using Inscriptionem.Extensions;
using Inscriptionem.Localization;
using Inscriptionem.Models.Enums;
using Inscriptionem.Models.Requests;
using Inscriptionem.Models.Views;
using Inscriptionem.Services;

namespace Inscriptionem.Controllers
{
    public class LoginController : BaseController
    {
        public ActionResult Index()
        {
            if (Member.Current.Role == MemberRole.None)
            {
                return View(new LoginViewModel() {Language = Language.Current.Value});
            }
            
            if (Member.Current.Role == MemberRole.Member)
            {
                return Redirect(string.Format("/{0}/Member", Language.Current.Value));
            }

            return Redirect("/Inscriptionem");
        }

        [HttpPost]
        public ActionResult Index(LoginRequestModel model)
        {
            var result = new LoginViewModel();
            model.CopyTo(result);

            if (string.IsNullOrWhiteSpace(model.Mail))
            {
                result.Error = LoginError.EmptyMail;
            }
            else if (!model.Mail.Contains("@"))
            {
                result.Error = LoginError.InvalidMail;
            }
            else if (string.IsNullOrWhiteSpace(model.Password))
            {
                result.Error = LoginError.EmptyPassword;
            }
            else
            {
                try
                {
                    result.Error = LoginService.Login(model.Mail, model.Password);
                }
                catch (Exception)
                {
                    result.Error = LoginError.Other;
                }
            }

            if (result.Error == LoginError.None)
            {
                if (Member.Current.Role == MemberRole.Member)
                {
                    return Redirect(string.Format("/{0}/", Language.Current.Value));
                }

                return Redirect("/Inscriptionem");
            }

            return View("Index", result);
        }

        public ActionResult Register()
        {
            if (Member.Current.Role != MemberRole.None)
            {
                return Redirect(Configuration.Configuration.Instance.General.URL);
            }

            if (!Configuration.Configuration.Instance.Members.RegistrationAllowed)
            {
                return View("RegistrationDisabled");
            }

            return View("Register", new RegisterViewModel() {Language = Language.Current.Value});
        }

        [HttpPost]
        public ActionResult Register(InstallRequestModel model)
        {
            if (Member.Current.Role != MemberRole.None)
            {
                return Redirect(Configuration.Configuration.Instance.General.URL);
            }

            if (!Configuration.Configuration.Instance.Members.RegistrationAllowed)
            {
                return View("RegistrationDisabled");
            }

            var viewModel = LoginService.ValidateRegisterRequest(model);

            if (viewModel.Error == RegisterError.None)
            {
                // Register
                try
                {
                    if (LoginService.Register(model))
                    {
                        // Login should always be successful
                        LoginService.Login(model.Mail, model.Password);
                        return Redirect(string.Format("/{0}/", Language.Current.Value));
                    }
                }
                catch (Exception)
                {
                    viewModel.Error = RegisterError.Other;
                }
            }

            return View("Register", viewModel);
        }

        public ActionResult Remind()
        {
            return View("Remind", new RemindViewModel() {Error = RemindError.None, Language = Language.Current.Value});
        }

        [HttpPost]
        public ActionResult Remind(RemindRequestModel model)
        {
            var result = new RemindViewModel();
            model.CopyTo(result);

            // Validation
            if (string.IsNullOrWhiteSpace(result.Mail))
            {
                result.Error = RemindError.EmptyMail;
            }
            else if (!result.Mail.Contains("@"))
            {
                result.Error = RemindError.InvalidMail;
            }

            if (result.Error != RemindError.None)
            {
                return View("Remind", result);
            }

            // Send mail
            try
            {
                var db = new ORM.DB();
                var member = db.Members.FirstOrDefault(m => m.Mail == result.Mail.ToLower());
                if (member == null)
                {
                    result.Error = RemindError.UnexistingMail;
                }
                else
                {
                    var reminder = new ORM.MemberPasswordRemind() {GUID = Guid.NewGuid(), IsActivated = false, CreatedDate = DateTime.Now, ModifiedDate = DateTime.Now};
                    member.MemberPasswordReminds.Add(reminder);
                    db.AddToMemberPasswordReminds(reminder);
                    db.SaveChanges();

                    MailService.SendPasswordReminder(member.Mail, reminder.GUID);
                }
            }
            catch (Exception)
            {
                result.Error = RemindError.Other;
            }

            return result.Error == RemindError.None ? View("RemindRequestSuccess") : View("Remind", result);
        }

        [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
        public ActionResult RemindChange(RemindChangeRequestModel model)
        {
            if (string.IsNullOrWhiteSpace(model.Mail) || !model.Mail.Contains("@"))
            {
                return View("RemindChangeExpired");
            }

            var result = new RemindChangeViewModel();
            model.CopyTo(result);

            try
            {
                var db = new ORM.DB();
                var memeber = db.Members.FirstOrDefault(m => m.Mail == model.Mail.ToLower());
                if (memeber == null)
                {
                    return View("RemindChangeExpired");
                }

                var remind = memeber.MemberPasswordReminds.FirstOrDefault(r => r.GUID == model.GUID);
                if (remind == null || remind.IsActivated)
                {
                    return View("RemindChangeExpired");
                }

                if (Request.RequestType.ToLower() == "post")
                {
                    // Check password
                    if (string.IsNullOrWhiteSpace(model.Password))
                    {
                        result.Error = RemindChangeError.PasswordEmpty;
                    }
                    else if (model.Password.Length < 6)
                    {
                        result.Error = RemindChangeError.PasswordLength;
                    }
                    else if (model.Password != model.PasswordConfirmation)
                    {
                        result.Error = RemindChangeError.PasswordNotMatched;
                    }
                    else
                    {
                        // Change password
                        LoginService.ChangePassword(model.Mail, model.Password);

                        remind.IsActivated = true;
                        db.SaveChanges();

                        return View("RemindChangeSuccess");
                    }
                }
            }
            catch (Exception)
            {
                result.Error = RemindChangeError.Other;
            }

            return View("RemindChange", result);
        }

        public ActionResult LogOff()
        {
            Member.Current = null;
            return Redirect("/" + Language.Current.Value);
        }
    }
}